@dinoxx/dinox-cli 1.0.22 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -9
- package/dist/auth/userInfo.d.ts +2 -0
- package/dist/auth/userInfo.js +55 -14
- package/dist/cli.js +36 -2
- package/dist/commands/auth/index.d.ts +35 -0
- package/dist/commands/auth/index.js +382 -83
- package/dist/commands/boxes/index.js +2 -6
- package/dist/commands/boxes/model.d.ts +3 -0
- package/dist/commands/boxes/model.js +16 -1
- package/dist/commands/boxes/operations.js +18 -8
- package/dist/commands/boxes/repo.js +13 -11
- package/dist/commands/boxes/store.js +1 -1
- package/dist/commands/config/index.js +7 -5
- package/dist/commands/descriptor/register.js +9 -0
- package/dist/commands/doctor.d.ts +123 -0
- package/dist/commands/doctor.js +539 -0
- package/dist/commands/graph/index.d.ts +1 -1
- package/dist/commands/graph/index.js +35 -21
- package/dist/commands/graph/repo.js +92 -17
- package/dist/commands/meta/index.js +4 -4
- package/dist/commands/meta/repo.js +4 -3
- package/dist/commands/notes/actions.d.ts +1 -1
- package/dist/commands/notes/actions.js +121 -78
- package/dist/commands/notes/bulk.d.ts +1 -0
- package/dist/commands/notes/bulk.js +23 -17
- package/dist/commands/notes/contentEngine.js +69 -11
- package/dist/commands/notes/contentPatch.d.ts +4 -1
- package/dist/commands/notes/contentPatch.js +105 -41
- package/dist/commands/notes/contentPatchCommand.js +28 -11
- package/dist/commands/notes/descriptors.js +50 -20
- package/dist/commands/notes/dryRun.d.ts +1 -0
- package/dist/commands/notes/dryRun.js +4 -7
- package/dist/commands/notes/export.d.ts +6 -0
- package/dist/commands/notes/export.js +26 -6
- package/dist/commands/notes/metadataMutation.d.ts +1 -0
- package/dist/commands/notes/metadataMutation.js +14 -3
- package/dist/commands/notes/repo.d.ts +46 -4
- package/dist/commands/notes/repo.js +113 -28
- package/dist/commands/notes/runtime.d.ts +2 -1
- package/dist/commands/notes/runtime.js +17 -1
- package/dist/commands/notes/searchSql.js +13 -6
- package/dist/commands/notes/writeReceipt.d.ts +20 -0
- package/dist/commands/notes/writeReceipt.js +82 -0
- package/dist/commands/prompt/index.js +3 -3
- package/dist/commands/prompt/repo.d.ts +4 -1
- package/dist/commands/prompt/repo.js +17 -7
- package/dist/commands/runtime.d.ts +14 -2
- package/dist/commands/runtime.js +74 -15
- package/dist/commands/schema/renderSkills.js +5 -2
- package/dist/commands/schema/spec.js +4 -0
- package/dist/commands/storage/index.js +8 -2
- package/dist/commands/storage/repo.d.ts +4 -0
- package/dist/commands/storage/repo.js +356 -92
- package/dist/commands/sync.js +16 -12
- package/dist/commands/tags/content.js +9 -0
- package/dist/commands/tags/index.js +2 -6
- package/dist/commands/tags/operations.js +15 -10
- package/dist/commands/tags/repo.d.ts +2 -0
- package/dist/commands/tags/repo.js +18 -5
- package/dist/commands/tags/store.js +1 -1
- package/dist/commands/todo/contentModel.d.ts +4 -3
- package/dist/commands/todo/contentModel.js +78 -28
- package/dist/commands/todo/dryRun.d.ts +1 -0
- package/dist/commands/todo/dryRun.js +17 -13
- package/dist/commands/todo/index.d.ts +6 -0
- package/dist/commands/todo/index.js +89 -123
- package/dist/commands/todo/repo.d.ts +36 -1
- package/dist/commands/todo/repo.js +146 -37
- package/dist/commands/todo/taskIdentity.d.ts +2 -0
- package/dist/commands/todo/taskIdentity.js +64 -0
- package/dist/commands/todo/taskModel.js +27 -17
- package/dist/commands/update.d.ts +13 -1
- package/dist/commands/update.js +135 -23
- package/dist/commands/writeDryRun.d.ts +3 -2
- package/dist/commands/writeDryRun.js +4 -3
- package/dist/commands/writeDurability.d.ts +5 -0
- package/dist/commands/writeDurability.js +22 -0
- package/dist/config/paths.js +6 -1
- package/dist/config/resolve.d.ts +2 -0
- package/dist/config/resolve.js +23 -9
- package/dist/config/store.d.ts +3 -0
- package/dist/config/store.js +61 -14
- package/dist/config/types.d.ts +4 -0
- package/dist/daemon/client.d.ts +26 -1
- package/dist/daemon/client.js +236 -12
- package/dist/daemon/ensure.js +74 -12
- package/dist/daemon/index.d.ts +42 -0
- package/dist/daemon/index.js +202 -52
- package/dist/daemon/lifecycle.d.ts +42 -0
- package/dist/daemon/lifecycle.js +115 -0
- package/dist/daemon/pid.d.ts +19 -6
- package/dist/daemon/pid.js +147 -13
- package/dist/daemon/route.d.ts +14 -0
- package/dist/daemon/route.js +40 -0
- package/dist/daemon/server.d.ts +11 -0
- package/dist/daemon/server.js +201 -50
- package/dist/daemon/types.d.ts +29 -1
- package/dist/daemon/types.js +1 -0
- package/dist/dinox.js +25 -1
- package/dist/powersync/connector.js +31 -16
- package/dist/powersync/exclusiveRuntime.d.ts +19 -0
- package/dist/powersync/exclusiveRuntime.js +42 -0
- package/dist/powersync/runtime.d.ts +24 -4
- package/dist/powersync/runtime.js +234 -36
- package/dist/powersync/syncGate.d.ts +3 -1
- package/dist/powersync/syncGate.js +7 -1
- package/dist/powersync/tokenIndex.d.ts +11 -0
- package/dist/powersync/tokenIndex.js +159 -22
- package/dist/powersync/uploader.js +107 -52
- package/dist/utils/abort.js +0 -4
- package/dist/utils/asyncRelease.d.ts +2 -0
- package/dist/utils/asyncRelease.js +25 -0
- package/dist/utils/bidlinkCanonicalization.js +3 -0
- package/dist/utils/dryRun.d.ts +1 -1
- package/dist/utils/errors.d.ts +15 -1
- package/dist/utils/errors.js +223 -5
- package/dist/utils/output.d.ts +1 -0
- package/dist/utils/output.js +51 -15
- package/dist/utils/redact.js +1 -1
- package/dist/utils/sqliteLease.d.ts +8 -0
- package/dist/utils/sqliteLease.js +59 -0
- package/dist/utils/syncTimeout.d.ts +7 -1
- package/dist/utils/syncTimeout.js +8 -7
- package/dist/utils/terminalSanitization.js +6 -2
- package/dist/utils/tiptapMarkdown.js +49 -3
- package/dist/utils/tiptapMarkdownSyntax.d.ts +9 -0
- package/dist/utils/tiptapMarkdownSyntax.js +249 -0
- package/dist/utils/tokenize.js +24 -2
- package/dist/utils/updateNotice.js +60 -12
- package/package.json +12 -10
- package/dist/commands/mcp/auth.d.ts +0 -4
- package/dist/commands/mcp/auth.js +0 -75
- package/dist/commands/mcp/index.d.ts +0 -2
- package/dist/commands/mcp/index.js +0 -86
- package/dist/commands/mcp/noteContentTools.d.ts +0 -222
- package/dist/commands/mcp/noteContentTools.js +0 -390
- package/dist/commands/mcp/server.d.ts +0 -34
- package/dist/commands/mcp/server.js +0 -424
- package/dist/commands/mcp/tools.d.ts +0 -2
- package/dist/commands/mcp/tools.js +0 -32
- package/dist/commands/mcp/types.d.ts +0 -39
- package/dist/commands/mcp/types.js +0 -1
- package/dist/utils/noteContentEngine.d.ts +0 -333
- package/dist/utils/noteContentEngine.js +0 -740
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Dinox CLI 适合这几类场景:
|
|
|
52
52
|
|
|
53
53
|
安装前请先确认:
|
|
54
54
|
|
|
55
|
-
-
|
|
55
|
+
- 推荐使用 Node.js 24 LTS;支持 Node.js 20.18.1+、22、23、24、25(不支持 Node.js 21 或 26+)
|
|
56
56
|
- 已安装 npm
|
|
57
57
|
- 你的系统可以正常执行全局 npm 命令
|
|
58
58
|
|
|
@@ -114,13 +114,15 @@ dino update
|
|
|
114
114
|
### 第 1 步:登录
|
|
115
115
|
|
|
116
116
|
```bash
|
|
117
|
-
|
|
117
|
+
read -rs DINOX_TOKEN
|
|
118
|
+
printf '%s' "$DINOX_TOKEN" | dino auth login --token-stdin
|
|
119
|
+
unset DINOX_TOKEN
|
|
118
120
|
```
|
|
119
121
|
|
|
120
122
|
说明:
|
|
121
123
|
|
|
122
|
-
-
|
|
123
|
-
- `
|
|
124
|
+
- 第一行会在当前终端隐藏输入 token,避免 token 出现在命令参数和 shell 历史中
|
|
125
|
+
- `--token-stdin` 接受 token 本体或 `Bearer ...`
|
|
124
126
|
- 登录时 CLI 会顺便验证连接是否可用
|
|
125
127
|
- 自动化或 CI 可以改用 `DINOX_TOKEN` 环境变量注入 token;它优先于本地配置,并支持 token 本体或 `Bearer ...`
|
|
126
128
|
|
|
@@ -452,7 +454,7 @@ dino note content-read <note-id> --format json
|
|
|
452
454
|
dino note patch <note-id> --append-section "复盘" --content @./section.md --read-token <token> --format json
|
|
453
455
|
```
|
|
454
456
|
|
|
455
|
-
`note patch` 只用于正文结构化编辑。真实写入前必须先 `content-read`,并传回 `readToken
|
|
457
|
+
`note patch` 只用于正文结构化编辑。真实写入前必须先 `content-read`,并传回 `readToken`;token 短期有效(当前为 30 分钟,以 `readTokenExpiresAt` 为准),绑定生成它时当前账号对应的本地 PowerSync 数据库作用域,不能在切换账号或本地数据库后复用。token 也是单次使用的,任何真实 patch 尝试都会先消费它,失败后重试必须重新执行 `content-read`。替换媒体、表格、未知节点等受保护 block 时,还需要显式 `--allow-protected-replace`。
|
|
456
458
|
|
|
457
459
|
#### 收藏状态
|
|
458
460
|
|
|
@@ -527,6 +529,7 @@ dino todo append --note-id <note-id> --tasks @./todo.txt
|
|
|
527
529
|
|
|
528
530
|
```bash
|
|
529
531
|
dino todo update <task-id> --status completed
|
|
532
|
+
dino todo update <task-id> --note-id <note-id> --status completed
|
|
530
533
|
dino todo update <task-id> --status uncompleted
|
|
531
534
|
```
|
|
532
535
|
|
|
@@ -542,6 +545,8 @@ dino todo update <task-id> --status false
|
|
|
542
545
|
- `completed`
|
|
543
546
|
- `uncompleted`
|
|
544
547
|
|
|
548
|
+
对没有持久 task id 的旧笔记,`todo search` 会返回 `legacy-task-*` 合成 id。该 id 绑定搜索时的任务位置和内容;如果笔记结构随后变化,更新会安全失败,必须重新搜索,避免把状态写到另一条任务。建议始终把搜索结果中的 `note_id` 一并传给 `--note-id`。
|
|
549
|
+
|
|
545
550
|
### 5.7 管理标签
|
|
546
551
|
|
|
547
552
|
#### 查看全部标签
|
|
@@ -655,7 +660,9 @@ dino note search "AI" --offline --format json
|
|
|
655
660
|
### 6.2 `auth`:登录与状态
|
|
656
661
|
|
|
657
662
|
```bash
|
|
658
|
-
|
|
663
|
+
read -rs DINOX_TOKEN
|
|
664
|
+
printf '%s' "$DINOX_TOKEN" | dino auth login --token-stdin
|
|
665
|
+
unset DINOX_TOKEN
|
|
659
666
|
dino auth status
|
|
660
667
|
dino auth logout
|
|
661
668
|
dino auth logout --clear-local-db
|
|
@@ -667,6 +674,8 @@ dino auth logout --clear-local-db
|
|
|
667
674
|
- `status`:查看登录状态、本地库位置、同步状态
|
|
668
675
|
- `logout`:退出登录
|
|
669
676
|
- `logout --clear-local-db`:退出并删除本地 SQLite 缓存
|
|
677
|
+
- logout 会优先清除配置中保存的凭据;若 daemon 停止、身份解析、数据库 owner lease 获取或释放、缓存删除失败,错误详情会返回 `persistedCredentialsCleared`、`cleanupPhase` 和缓存路径。CLI 会尝试释放全部已取得的 lease;即使某个 release 失败,也不会跳过后续 release 或覆盖更早的主错误。此时凭据已清,但不能认为本地清理已安全完成。
|
|
678
|
+
- 当前 shell 中的 `DINOX_TOKEN` 不受 logout 影响;结果中的 `environmentTokenActive: true` 表示该环境仍可认证。
|
|
670
679
|
|
|
671
680
|
### 6.3 `sync`:手动同步
|
|
672
681
|
|
|
@@ -755,6 +764,7 @@ dino todo update <task-id> --status completed
|
|
|
755
764
|
- `--dry-run`
|
|
756
765
|
- `todo update`
|
|
757
766
|
- `--status <status>` 必填
|
|
767
|
+
- `--note-id <id>`:用搜索结果中的笔记 id 精确限定目标
|
|
758
768
|
- `--dry-run`
|
|
759
769
|
|
|
760
770
|
### 6.6 `tag`:标签管理
|
|
@@ -806,8 +816,9 @@ dino graph stats
|
|
|
806
816
|
说明:
|
|
807
817
|
|
|
808
818
|
- 这些命令用于查看笔记之间的链接关系
|
|
809
|
-
- 在线模式下,CLI 会自动确保 daemon
|
|
819
|
+
- 在线模式下,CLI 会自动确保 daemon 可用,并通过 daemon-owned DB runtime 执行
|
|
810
820
|
- 如果你只想用本地缓存而不启动 daemon,可加 `--offline`
|
|
821
|
+
- 如果 daemon 不可用,默认在线模式会返回带 `suggested_action` 的结构化错误;不会静默回退到另一个进程打开本地 DB
|
|
811
822
|
|
|
812
823
|
例如:
|
|
813
824
|
|
|
@@ -835,6 +846,7 @@ dino storage test
|
|
|
835
846
|
dino storage test --storage-id <id>
|
|
836
847
|
dino storage upload ./report.pdf
|
|
837
848
|
dino storage upload ./photo.jpg --category images
|
|
849
|
+
dino storage upload ./report.pdf --key imports/report.pdf --overwrite
|
|
838
850
|
dino storage stats
|
|
839
851
|
```
|
|
840
852
|
|
|
@@ -846,7 +858,9 @@ dino storage stats
|
|
|
846
858
|
- `storage upload` 会上传本地文件,并写入资源记录
|
|
847
859
|
- 如果不是上传到当前活动存储,可用 `--storage-id <id>` 指定目标
|
|
848
860
|
- `--category` 支持:`images`、`audios`、`files`、`videos`
|
|
849
|
-
- 如果你想自己指定对象 key,可用 `--key <string
|
|
861
|
+
- 如果你想自己指定对象 key,可用 `--key <string>`;key 和存储路径前缀不能包含纯 `.` 或 `..` 路径段,否则标准 URL 客户端会把路径归一化到错误对象
|
|
862
|
+
- 显式 `--key` 默认拒绝覆盖已有主对象或图片缩略图;只有在确认替换这些精确 key 后才使用 `--overwrite`
|
|
863
|
+
- 使用 `--overwrite` 时,一旦远端对象写入成功,后续缩略图或资源 metadata 记录失败不会自动删除已经写入的远端对象。不要把命令失败理解为远端已回滚;请检查结构化错误详情中的 `remoteObjectChanged`、`affectedKeys` 和主对象 `storageKey`,再核查或重试相关 key
|
|
850
864
|
- `--dry-run` 非常适合在正式上传前确认目标位置
|
|
851
865
|
|
|
852
866
|
### 6.13 `schema`:查看命令 schema
|
|
@@ -884,6 +898,10 @@ dino daemon start --no-detach
|
|
|
884
898
|
dino schema daemon.start --format json
|
|
885
899
|
```
|
|
886
900
|
|
|
901
|
+
daemon 通过用户数据目录下的私有 Unix domain socket 通信,Windows 使用命名管道;`--port` 仅保留给旧脚本作为兼容字段,不再作为监听地址。
|
|
902
|
+
|
|
903
|
+
需要在当前进程打开 PowerSync SQLite 的命令(例如写命令、`sync`、在线 `auth status`、`--offline` 或 `--require-sync` 读取)会先取得跨进程生命周期锁。如果同一用户数据库正由健康 daemon 持有,CLI 会暂时停止该实例;只有在命令结束、数据库关闭且 owner lease 成功释放后,才会按原端口恢复它。使用其他用户数据库的 daemon 不会被停止;如果关闭或释放失败,CLI 会保留 daemon 为停止状态并在 stderr 报告警告,避免两个运行时同时持有同一 SQLite 数据库。
|
|
904
|
+
|
|
887
905
|
### 6.15 `info`:查看版本与技能仓库地址
|
|
888
906
|
|
|
889
907
|
```bash
|
|
@@ -935,7 +953,9 @@ schema 包含命令路径、风险级别、参数、选项、输出字段和示
|
|
|
935
953
|
解决:
|
|
936
954
|
|
|
937
955
|
```bash
|
|
938
|
-
|
|
956
|
+
read -rs DINOX_TOKEN
|
|
957
|
+
printf '%s' "$DINOX_TOKEN" | dino auth login --token-stdin
|
|
958
|
+
unset DINOX_TOKEN
|
|
939
959
|
dino sync
|
|
940
960
|
```
|
|
941
961
|
|
package/dist/auth/userInfo.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type AuthIdentity = {
|
|
|
5
5
|
email: string | null;
|
|
6
6
|
syncedAt: string;
|
|
7
7
|
};
|
|
8
|
+
export declare function persistedAuthStateMatches(left: DinoxConfig, right: DinoxConfig): boolean;
|
|
9
|
+
export declare function rotatePersistedAuthStateRevision(config: DinoxConfig): DinoxConfig;
|
|
8
10
|
export declare function buildPendingAuthConfig(rawConfig: DinoxConfig, authorization: string): DinoxConfig;
|
|
9
11
|
export declare function mergeAuthIdentityIntoConfig(rawConfig: DinoxConfig, authorization: string, identity: AuthIdentity): DinoxConfig;
|
|
10
12
|
export declare function fetchUserInfoWithAuthorization(input: {
|
package/dist/auth/userInfo.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
import { updateConfig } from '../config/store.js';
|
|
2
3
|
import { DinoxError } from '../utils/errors.js';
|
|
3
4
|
import { createTimeoutSignal, mergeAbortSignals } from '../utils/abort.js';
|
|
4
|
-
import { toAuthorizationHeaderValue } from '../utils/authToken.js';
|
|
5
|
+
import { normalizeAuthToken, toAuthorizationHeaderValue } from '../utils/authToken.js';
|
|
6
|
+
import { generateId } from '../utils/id.js';
|
|
5
7
|
const AUTH_CODE_OK = '000000';
|
|
8
|
+
export function persistedAuthStateMatches(left, right) {
|
|
9
|
+
return isDeepStrictEqual(left.auth ?? {}, right.auth ?? {});
|
|
10
|
+
}
|
|
11
|
+
export function rotatePersistedAuthStateRevision(config) {
|
|
12
|
+
return {
|
|
13
|
+
...config,
|
|
14
|
+
auth: {
|
|
15
|
+
...(config.auth ?? {}),
|
|
16
|
+
stateRevision: generateId(),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
6
20
|
export function buildPendingAuthConfig(rawConfig, authorization) {
|
|
7
21
|
return {
|
|
8
22
|
...rawConfig,
|
|
@@ -73,9 +87,9 @@ function parseIdentity(payload) {
|
|
|
73
87
|
};
|
|
74
88
|
}
|
|
75
89
|
function resolveUserInfoEndpoint(config) {
|
|
76
|
-
const base = normalizeOptionalString(config.powersync.
|
|
90
|
+
const base = normalizeOptionalString(config.powersync.tokenEndpoint);
|
|
77
91
|
if (!base) {
|
|
78
|
-
throw new DinoxError('Missing
|
|
92
|
+
throw new DinoxError('Missing PowerSync token endpoint for user info');
|
|
79
93
|
}
|
|
80
94
|
try {
|
|
81
95
|
const url = new URL('/auth/userInfo', base);
|
|
@@ -96,9 +110,8 @@ export async function fetchUserInfoWithAuthorization(input) {
|
|
|
96
110
|
? createTimeoutSignal(effectiveTimeoutMs)
|
|
97
111
|
: null;
|
|
98
112
|
const requestSignal = mergeAbortSignals([input.signal, timeout?.signal]);
|
|
99
|
-
let response;
|
|
100
113
|
try {
|
|
101
|
-
response = await fetch(endpoint, {
|
|
114
|
+
const response = await fetch(endpoint, {
|
|
102
115
|
method: 'GET',
|
|
103
116
|
headers: {
|
|
104
117
|
Authorization: toAuthorizationHeaderValue(authorization),
|
|
@@ -106,6 +119,28 @@ export async function fetchUserInfoWithAuthorization(input) {
|
|
|
106
119
|
},
|
|
107
120
|
signal: requestSignal,
|
|
108
121
|
});
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
let body = '';
|
|
124
|
+
try {
|
|
125
|
+
body = await response.text();
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (requestSignal?.aborted) {
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
throw new DinoxError(`User info request failed (${response.status}): ${body || endpoint}`);
|
|
133
|
+
}
|
|
134
|
+
let payload = null;
|
|
135
|
+
try {
|
|
136
|
+
payload = await response.json();
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (requestSignal?.aborted) {
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return parseIdentity(payload);
|
|
109
144
|
}
|
|
110
145
|
catch (error) {
|
|
111
146
|
if (timeout?.signal.aborted && !input.signal?.aborted) {
|
|
@@ -116,12 +151,6 @@ export async function fetchUserInfoWithAuthorization(input) {
|
|
|
116
151
|
finally {
|
|
117
152
|
timeout?.cancel();
|
|
118
153
|
}
|
|
119
|
-
if (!response.ok) {
|
|
120
|
-
const body = await response.text().catch(() => '');
|
|
121
|
-
throw new DinoxError(`User info request failed (${response.status}): ${body || endpoint}`);
|
|
122
|
-
}
|
|
123
|
-
const payload = await response.json().catch(() => null);
|
|
124
|
-
return parseIdentity(payload);
|
|
125
154
|
}
|
|
126
155
|
export async function refreshAndPersistAuthIdentity(rawConfig, resolvedConfig) {
|
|
127
156
|
const authorization = normalizeOptionalString(resolvedConfig.auth.authorization);
|
|
@@ -132,8 +161,20 @@ export async function refreshAndPersistAuthIdentity(rawConfig, resolvedConfig) {
|
|
|
132
161
|
authorization,
|
|
133
162
|
config: resolvedConfig,
|
|
134
163
|
});
|
|
135
|
-
|
|
136
|
-
|
|
164
|
+
// Environment-only credentials are process-scoped and must never be copied into config.json.
|
|
165
|
+
if (normalizeAuthToken(rawConfig.auth?.authorization) !== authorization) {
|
|
166
|
+
return identity;
|
|
167
|
+
}
|
|
168
|
+
await updateConfig((current) => {
|
|
169
|
+
if (!persistedAuthStateMatches(current, rawConfig)) {
|
|
170
|
+
throw new DinoxError('Authentication changed while user identity was being refreshed.', {
|
|
171
|
+
code: 'AUTH_STATE_CHANGED',
|
|
172
|
+
suggestion: 'Retry the command so it uses the current login.',
|
|
173
|
+
recoverable: true,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return mergeAuthIdentityIntoConfig(current, authorization, identity);
|
|
177
|
+
}, { timeoutMs: resolvedConfig.sync.timeoutMs });
|
|
137
178
|
return identity;
|
|
138
179
|
}
|
|
139
180
|
function authIdentityFromResolvedConfig(resolvedConfig) {
|
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,7 @@ import { registerAuthCommands } from './commands/auth/index.js';
|
|
|
3
3
|
import { registerBoxesCommand } from './commands/boxes/index.js';
|
|
4
4
|
import { registerConfigCommands } from './commands/config/index.js';
|
|
5
5
|
import { registerDaemonCommands } from './daemon/index.js';
|
|
6
|
+
import { registerDoctorCommand } from './commands/doctor.js';
|
|
6
7
|
import { registerGraphCommands } from './commands/graph/index.js';
|
|
7
8
|
import { registerInfoCommand } from './commands/info/index.js';
|
|
8
9
|
import { registerMetaCommands } from './commands/meta/index.js';
|
|
@@ -15,15 +16,47 @@ import { registerUpdateCommand } from './commands/update.js';
|
|
|
15
16
|
import { registerTagsCommand } from './commands/tags/index.js';
|
|
16
17
|
import { registerTodoCommands } from './commands/todo/index.js';
|
|
17
18
|
import { getPackageVersion } from './utils/version.js';
|
|
18
|
-
import {
|
|
19
|
+
import { buildStructuredErrorPayload, DinoxError } from './utils/errors.js';
|
|
20
|
+
import { clearRequestedStructuredOutputFormat, parseStructuredOutputFormatFromArgv, printError, resolveStructuredOutputFormat, setRequestedStructuredOutputFormat, } from './utils/output.js';
|
|
19
21
|
export function createCli() {
|
|
20
22
|
clearRequestedStructuredOutputFormat();
|
|
21
23
|
const program = new Command();
|
|
24
|
+
let structuredCommanderErrorWritten = false;
|
|
22
25
|
program
|
|
23
26
|
.name('dino')
|
|
24
27
|
.description('Dinox CLI')
|
|
25
28
|
.version(getPackageVersion())
|
|
26
|
-
.showHelpAfterError()
|
|
29
|
+
.showHelpAfterError()
|
|
30
|
+
.configureOutput({
|
|
31
|
+
writeErr: (text) => {
|
|
32
|
+
if (!structuredCommanderErrorWritten) {
|
|
33
|
+
process.stderr.write(text);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
outputError: (text, write) => {
|
|
37
|
+
let format = null;
|
|
38
|
+
try {
|
|
39
|
+
const rawArgs = program.rawArgs ?? process.argv;
|
|
40
|
+
format = parseStructuredOutputFormatFromArgv(rawArgs.slice(2));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
write(text);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!format) {
|
|
47
|
+
write(text);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
structuredCommanderErrorWritten = true;
|
|
51
|
+
const message = text.trim().replace(/^error:\s*/i, '');
|
|
52
|
+
const error = new DinoxError(message, {
|
|
53
|
+
code: 'USAGE_ERROR',
|
|
54
|
+
recoverable: true,
|
|
55
|
+
});
|
|
56
|
+
printError(buildStructuredErrorPayload(error, false), format);
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
.exitOverride();
|
|
27
60
|
program
|
|
28
61
|
.option('--json', 'legacy machine-readable YAML output (equivalent to --format yaml)')
|
|
29
62
|
.option('--format <format>', 'structured output format: yaml | json')
|
|
@@ -42,6 +75,7 @@ export function createCli() {
|
|
|
42
75
|
registerBoxesCommand(program);
|
|
43
76
|
registerConfigCommands(program);
|
|
44
77
|
registerDaemonCommands(program);
|
|
78
|
+
registerDoctorCommand(program);
|
|
45
79
|
registerGraphCommands(program);
|
|
46
80
|
registerInfoCommand(program);
|
|
47
81
|
registerMetaCommands(program);
|
|
@@ -1,4 +1,39 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import { fetchUserInfoWithAuthorization } from '../../auth/userInfo.js';
|
|
3
|
+
import { loadConfig, updateConfig } from '../../config/store.js';
|
|
4
|
+
import { resolveConfig } from '../../config/resolve.js';
|
|
5
|
+
import { restoreSuspendedDaemonLocked, suspendDaemonForExclusiveAccessLocked } from '../../daemon/lifecycle.js';
|
|
6
|
+
import { acquireDaemonStartLock } from '../../daemon/pid.js';
|
|
7
|
+
import { fetchCredentialsWithAuthorization } from '../../powersync/connector.js';
|
|
8
|
+
import { closePowerSyncAndReleaseOwner, connectPowerSync, getStatusSnapshot } from '../../powersync/runtime.js';
|
|
9
|
+
import { runSingleSyncPass } from '../../powersync/syncPass.js';
|
|
2
10
|
import type { CommandGroupDescriptor } from '../descriptor/types.js';
|
|
11
|
+
import { printHumanReadableWarning } from '../../utils/output.js';
|
|
12
|
+
export declare function releaseOwnerLeases(releases: ReadonlyArray<() => Promise<void>>): Promise<unknown[]>;
|
|
13
|
+
type AuthLoginDependencies = {
|
|
14
|
+
acquireDaemonStartLock: typeof acquireDaemonStartLock;
|
|
15
|
+
loadConfig: typeof loadConfig;
|
|
16
|
+
resolveConfig: typeof resolveConfig;
|
|
17
|
+
fetchCredentials: typeof fetchCredentialsWithAuthorization;
|
|
18
|
+
fetchUserInfo: typeof fetchUserInfoWithAuthorization;
|
|
19
|
+
suspendDaemon: typeof suspendDaemonForExclusiveAccessLocked;
|
|
20
|
+
connectPowerSync: typeof connectPowerSync;
|
|
21
|
+
runSingleSyncPass: typeof runSingleSyncPass;
|
|
22
|
+
getStatusSnapshot: typeof getStatusSnapshot;
|
|
23
|
+
closePowerSyncAndReleaseOwner: typeof closePowerSyncAndReleaseOwner;
|
|
24
|
+
updateConfig: typeof updateConfig;
|
|
25
|
+
restoreDaemon: typeof restoreSuspendedDaemonLocked;
|
|
26
|
+
printWarning: typeof printHumanReadableWarning;
|
|
27
|
+
};
|
|
28
|
+
export declare function performAuthLogin(rawToken: string, syncTimeout: unknown, overrides?: Partial<AuthLoginDependencies>): Promise<{
|
|
29
|
+
ok: true;
|
|
30
|
+
verified: true;
|
|
31
|
+
endpoint: string;
|
|
32
|
+
dbPath: string;
|
|
33
|
+
stale: boolean;
|
|
34
|
+
lastSyncedAt: string | null;
|
|
35
|
+
userId: string;
|
|
36
|
+
}>;
|
|
3
37
|
export declare const authCommandGroup: CommandGroupDescriptor;
|
|
4
38
|
export declare function registerAuthCommands(program: Command): void;
|
|
39
|
+
export {};
|